﻿Imports System
Imports System.Windows.Forms
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports Microsoft.Win32

Public Class LibVLCold

    Private m_iVlcHandle As Integer = -1
    Private m_wndOutput As Control = Nothing
    Private m_strVlcInstallDir As String = ""
    Private m_strLastErr As String = ""

    Public Enum Err
        Success = -&H0
        NoMem = -&H1
        Thread = -&H2
        Timeout = -&H3
        NoMod = -&HA
        NoObj = -&H14
        BadObj = -&H14
        NoVar = -&H1E
        BadVar = -&H1F
        Close = -&HFF
        Generic = -&H29A
        Execption = -&H3E6
        NoInit = -&H3E7
    End Enum

    Enum Mode
        Insert = &H1
        Replace = &H2
        Append = &H4
        Go = &H8
        CheckInsert = &H10
    End Enum

    Enum Pos
        Close = -&H29A
    End Enum

    <StructLayout(LayoutKind.Explicit)> _
    Public Structure vlc_value_t
        <FieldOffset(0)> _
        Public i_int As Int32
        <FieldOffset(0)> _
        Public b_bool As Int32
        <FieldOffset(0)> _
        Public f_float As Single
        <FieldOffset(0)> _
        Public psz_string As IntPtr
        <FieldOffset(0)> _
        Public p_address As IntPtr
        <FieldOffset(0)> _
        Public p_object As IntPtr
        <FieldOffset(0)> _
        Public p_list As IntPtr
        <FieldOffset(0)> _
        Public i_time As Int64
        <FieldOffset(0)> _
        Public psz_name As IntPtr
        <FieldOffset(4)> _
        Public i_object_id As Int32
    End Structure

    Public Sub New()
        MyBase.New()
        m_strVlcInstallDir = System.AppDomain.CurrentDomain.BaseDirectory
        'QueryVlcInstallPath()
    End Sub

    Public Property VlcInstallDir() As String
        Get
            Return m_strVlcInstallDir
        End Get
        Set(ByVal Value As String)
            m_strVlcInstallDir = Value
        End Set
    End Property

    Public ReadOnly Property IsInitialized() As Boolean
        Get
            Return (m_iVlcHandle <> -1)
        End Get
    End Property

    Public Property VideoOutput() As Control
        Get
            Return m_wndOutput
        End Get
        Set(ByVal Value As Control)
            ' clear old window
            If (Not (m_wndOutput) Is Nothing) Then
                RemoveHandler m_wndOutput.Resize, AddressOf Me.wndOutput_Resize
                m_wndOutput = Nothing
                If (m_iVlcHandle <> -1) Then
                    SetVariable("drawable", 0)
                End If
            End If
            ' set new
            m_wndOutput = Value
            If (Not (m_wndOutput) Is Nothing) Then
                If (m_iVlcHandle <> -1) Then
                    SetVariable("drawable", m_wndOutput.Handle.ToInt32)
                End If
                AddHandler m_wndOutput.Resize, AddressOf Me.wndOutput_Resize
                wndOutput_Resize(Nothing, Nothing)
            End If
        End Set
    End Property

    Public ReadOnly Property LastErr() As String
        Get
            Return m_strLastErr
        End Get
    End Property

    Public ReadOnly Property IsPlaying() As Boolean
        Get
            If (m_iVlcHandle = -1) Then
                m_strLastErr = "LibVlc is not initialzed"
                Return False
            End If
            Try
                Return VLC_IsPlaying(m_iVlcHandle)
            Catch ex As Exception
                m_strLastErr = ex.Message
                Return False
            End Try
        End Get
    End Property

    Public ReadOnly Property LengthGet() As Integer
        Get
            If (m_iVlcHandle = -1) Then
                m_strLastErr = "LibVlc is not initialzed"
                Return -1
            End If
            Try
                Return VLC_LengthGet(m_iVlcHandle)
            Catch ex As Exception
                m_strLastErr = ex.Message
                Return -1
            End Try
        End Get
    End Property

    Public ReadOnly Property TimeGet() As Integer
        Get
            If (m_iVlcHandle = -1) Then
                m_strLastErr = "LibVlc is not initialzed"
                Return -1
            End If
            Try
                Return VLC_TimeGet(m_iVlcHandle)
            Catch ex As Exception
                m_strLastErr = ex.Message
                Return -1
            End Try
        End Get
    End Property

    Public ReadOnly Property PositionGet() As Single
        Get
            If (m_iVlcHandle = -1) Then
                m_strLastErr = "LibVlc is not initialzed"
                Return -1
            End If
            Try
                Return VLC_PositionGet(m_iVlcHandle)
            Catch ex As Exception
                m_strLastErr = ex.Message
                Return -1
            End Try
        End Get
    End Property

    Public ReadOnly Property VersionInfo() As String
        Get
            Return VLC_Version
        End Get
    End Property

    Public ReadOnly Property VolumeGet() As Integer
        Get
            If (m_iVlcHandle = -1) Then
                m_strLastErr = "LibVlc is not initialzed"
                Return -1
            End If
            Try
                Return VLC_VolumeGet(m_iVlcHandle)
            Catch ex As Exception
                m_strLastErr = ex.Message
                Return -1
            End Try
        End Get
    End Property

    Public Property Fullscreen() As Boolean
        Get
            Dim iIsFullScreen As Integer = 0
            If (GetVariable("fullscreen", iIsFullScreen) = Err.Success) Then
                If (iIsFullScreen <> 0) Then
                    Return True
                End If
            End If
            Return False
        End Get
        Set(ByVal Value As Boolean)
            Dim iFullScreen As Integer = Value
            'TODO: Warning!!!, inline IF is not supported ?

            SetVariable("fullscreen", iFullScreen)
        End Set
    End Property

    Private Declare Function VLC_Create Lib "libvlc" () As Integer

    Private Declare Function VLC_Init Lib "libvlc" (ByVal iVLC As Integer, ByVal Argc As Integer, ByVal Argv() As String) As Err

    Private Declare Function VLC_AddIntf Lib "libvlc" (ByVal iVLC As Integer, ByVal Name As String, ByVal Block As Boolean, ByVal Play As Boolean) As Err

    Private Declare Function VLC_Die Lib "libvlc" (ByVal iVLC As Integer) As Err

    Private Overloads Declare Function VLC_Err Lib "libvlc" () As String

    Private Declare Function VLC_Version Lib "libvlc" () As String

    Private Declare Function VLC_CleanUp Lib "libvlc" (ByVal iVLC As Integer) As Err

    Private Declare Function VLC_Destroy Lib "libvlc" (ByVal iVLC As Integer) As Err

    Private Declare Function VLC_AddTarget Lib "libvlc" (ByVal iVLC As Integer, ByVal Target As String, ByVal Options() As String, ByVal OptionsCount As Integer, ByVal Mode As Integer, ByVal Pos As Integer) As Err

    Private Declare Function VLC_Play Lib "libvlc" (ByVal iVLC As Integer) As Err

    Private Declare Function VLC_Pause Lib "libvlc" (ByVal iVLC As Integer) As Err

    Private Declare Function VLC_Stop Lib "libvlc" (ByVal iVLC As Integer) As Err

    Private Declare Function VLC_IsPlaying Lib "libvlc" (ByVal iVLC As Integer) As Boolean

    Private Declare Function VLC_PositionGet Lib "libvlc" (ByVal iVLC As Integer) As Single

    Private Declare Function VLC_PositionSet Lib "libvlc" (ByVal iVLC As Integer, ByVal Pos As Single) As Single

    Private Declare Function VLC_TimeGet Lib "libvlc" (ByVal iVLC As Integer) As Integer

    Private Declare Function VLC_TimeSet Lib "libvlc" (ByVal iVLC As Integer, ByVal Seconds As Integer, ByVal Relative As Boolean) As Err

    Private Declare Function VLC_LengthGet Lib "libvlc" (ByVal iVLC As Integer) As Integer

    Private Declare Function VLC_SpeedFaster Lib "libvlc" (ByVal iVLC As Integer) As Single

    Private Declare Function VLC_SpeedSlower Lib "libvlc" (ByVal iVLC As Integer) As Single

    Private Declare Function VLC_PlaylistIndex Lib "libvlc" (ByVal iVLC As Integer) As Integer

    Private Declare Function VLC_PlaylistNumberOfItems Lib "libvlc" (ByVal iVLC As Integer) As Integer

    Private Declare Function VLC_PlaylistNext Lib "libvlc" (ByVal iVLC As Integer) As Err

    Private Declare Function VLC_PlaylistPrev Lib "libvlc" (ByVal iVLC As Integer) As Err

    Private Declare Function VLC_PlaylistClear Lib "libvlc" (ByVal iVLC As Integer) As Err

    Private Declare Function VLC_VolumeSet Lib "libvlc" (ByVal iVLC As Integer, ByVal Volume As Integer) As Integer

    Private Declare Function VLC_VolumeGet Lib "libvlc" (ByVal iVLC As Integer) As Integer

    Private Declare Function VLC_VolumeMute Lib "libvlc" (ByVal iVLC As Integer) As Err

    Private Declare Function VLC_FullScreen Lib "libvlc" (ByVal iVLC As Integer) As Err

    Private Declare Function VLC_VariableType Lib "libvlc" (ByVal iVLC As Integer, ByVal Name As String, ByRef iType As Integer) As Err

    Private Declare Function VLC_VariableSet Lib "libvlc" (ByVal iVLC As Integer, ByVal Name As String, ByVal value As vlc_value_t) As Err

    Private Declare Function VLC_VariableGet Lib "libvlc" (ByVal iVLC As Integer, ByVal Name As String, ByRef value As vlc_value_t) As Err

    Private Overloads Declare Function VLC_Err Lib "libvlc" (ByVal i_err As Integer) As String

    Public Sub Dispose()
        If (m_iVlcHandle <> -1) Then
            Try
                VLC_CleanUp(m_iVlcHandle)
                VLC_Destroy(m_iVlcHandle)
                VideoOutput = Nothing
            Catch ex As System.Exception

            End Try
        End If
        m_iVlcHandle = -1
    End Sub

    Public Function Initialize() As Boolean
        ' check if already initializes
        If (m_iVlcHandle <> -1) Then
            Return True
        End If
        ' try init
        Try
            ' create instance
            m_iVlcHandle = VLC_Create
            If (m_iVlcHandle < 0) Then
                m_strLastErr = "Failed to create VLC instance"
                Return False
            End If
            ' make init optinons
            Dim strInitOptions As String() = {"vlc", "--no-one-instance", "--no-loop", "--no-drop-late-frames", "--disable-screensaver"}
            'If m_strVlcInstallDir.Length > 0 Then
            'strInitOptions(0) = m_strVlcInstallDir & "\vlc"
            'End If
            ' init libvlc
            Dim errVlcLib As Err = VLC_Init(m_iVlcHandle, strInitOptions.Length, strInitOptions)
            'MessageBox.Show(strInitOptions(1))
            If (errVlcLib <> Err.Success) Then
                VLC_Destroy(m_iVlcHandle)
                m_strLastErr = "Failed to initialise VLC"
                m_iVlcHandle = -1
                Return False
            End If
        Catch ex As System.Exception
            m_strLastErr = "Could not find libvlc"
            Return False
        End Try
        ' check output window
        If (Not (m_wndOutput) Is Nothing) Then
            SetVariable("drawable", m_wndOutput.Handle.ToInt32)
            wndOutput_Resize(Nothing, Nothing)
        End If
        ' OK
        Return True
    End Function

    Public Overloads Function AddTarget(ByVal Target As String) As Err
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return Err.NoInit
        End If
        Dim enmErr As Err = Err.Success
        Try
            enmErr = VLC_AddTarget(m_iVlcHandle, Target, Nothing, 0, CType(Mode.Append, Integer), CType(Pos.Close, Integer))
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return Err.Execption
        End Try
        If (CType(enmErr, Integer) < 0) Then
            m_strLastErr = VLC_Err(CType(enmErr, Integer))
            Return enmErr
        End If
        ' OK
        Return Err.Success
    End Function

    Public Overloads Function AddTarget(ByVal Target As String, ByVal Options() As String) As Err
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return Err.NoInit
        End If
        ' check options
        Dim iOptionsCount As Integer = 0
        If (Not (Options) Is Nothing) Then
            iOptionsCount = Options.Length
        End If
        ' add
        Dim enmErr As Err = Err.Success
        Try
            enmErr = VLC_AddTarget(m_iVlcHandle, Target, Options, iOptionsCount, CType(Mode.Append, Integer), CType(Pos.Close, Integer))
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return Err.Execption
        End Try
        If (CType(enmErr, Integer) < 0) Then
            m_strLastErr = VLC_Err(CType(enmErr, Integer))
            Return enmErr
        End If
        ' OK
        Return Err.Success
    End Function

    Public Function Play() As Err
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return Err.NoInit
        End If
        Dim enmErr As Err = Err.Success
        Try
            enmErr = VLC_Play(m_iVlcHandle)
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return Err.Execption
        End Try
        If (CType(enmErr, Integer) < 0) Then
            m_strLastErr = VLC_Err(CType(enmErr, Integer))
            Return enmErr
        End If
        ' OK
        Return Err.Success
    End Function

    Public Function Pause() As Err
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return Err.NoInit
        End If
        Dim enmErr As Err = Err.Success
        Try
            enmErr = VLC_Pause(m_iVlcHandle)
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return Err.Execption
        End Try
        If (CType(enmErr, Integer) < 0) Then
            m_strLastErr = VLC_Err(CType(enmErr, Integer))
            Return enmErr
        End If
        ' OK
        Return Err.Success
    End Function

    Public Function StopAudio() As Err
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return Err.NoInit
        End If
        Dim enmErr As Err = Err.Success
        Try
            enmErr = VLC_Stop(m_iVlcHandle)
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return Err.Execption
        End Try
        If (CType(enmErr, Integer) < 0) Then
            m_strLastErr = VLC_Err(CType(enmErr, Integer))
            Return enmErr
        End If
        ' OK
        Return Err.Success
    End Function

    Public Function SpeedFaster() As Single
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return -1
        End If
        Dim enmErr As Err = Err.Success
        Try
            Return VLC_SpeedFaster(m_iVlcHandle)
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return -1
        End Try
    End Function

    Public Function SpeedSlower() As Single
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return -1
        End If
        Dim enmErr As Err = Err.Success
        Try
            Return VLC_SpeedSlower(m_iVlcHandle)
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return -1
        End Try
    End Function

    Public Function PlaylistNext() As Err
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return Err.NoInit
        End If
        Dim enmErr As Err = Err.Success
        Try
            enmErr = VLC_PlaylistNext(m_iVlcHandle)
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return Err.Execption
        End Try
        If (CType(enmErr, Integer) < 0) Then
            m_strLastErr = VLC_Err(CType(enmErr, Integer))
            Return enmErr
        End If
        ' OK
        Return Err.Success
    End Function

    Public Function PlaylistPrevious() As Err
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return Err.NoInit
        End If
        Dim enmErr As Err = Err.Success
        Try
            enmErr = VLC_PlaylistPrev(m_iVlcHandle)
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return Err.Execption
        End Try
        If (CType(enmErr, Integer) < 0) Then
            m_strLastErr = VLC_Err(CType(enmErr, Integer))
            Return enmErr
        End If
        ' OK
        Return Err.Success
    End Function

    Public Function PlaylistClear() As Err
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return Err.NoInit
        End If
        Dim enmErr As Err = Err.Success
        Try
            enmErr = VLC_PlaylistClear(m_iVlcHandle)
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return Err.Execption
        End Try
        If (CType(enmErr, Integer) < 0) Then
            m_strLastErr = VLC_Err(CType(enmErr, Integer))
            Return enmErr
        End If
        ' OK
        Return Err.Success
    End Function


    Public Function TimeSet(ByVal newPosition As Integer, ByVal bRelative As Boolean) As Err
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return Err.NoInit
        End If
        Dim enmErr As Err = Err.Success
        Try
            enmErr = VLC_TimeSet(m_iVlcHandle, newPosition, bRelative)
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return Err.Execption
        End Try
        If (CType(enmErr, Integer) < 0) Then
            m_strLastErr = VLC_Err(CType(enmErr, Integer))
            Return enmErr
        End If
        ' OK
        Return Err.Success
    End Function

    Public Function PositionSet(ByVal newPosition As Single) As Single
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return -1
        End If
        Try
            Return VLC_PositionSet(m_iVlcHandle, newPosition)
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return -1
        End Try
    End Function

    Public Function VolumeSet(ByVal newVolume As Integer) As Integer
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return -1
        End If
        Dim enmErr As Err = Err.Success
        Try
            Return VLC_VolumeSet(m_iVlcHandle, newVolume)
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return -1
        End Try
    End Function

    Public Function VolumeMute() As Err
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return Err.NoInit
        End If
        Dim enmErr As Err = Err.Success
        Try
            enmErr = VLC_VolumeMute(m_iVlcHandle)
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return Err.Execption
        End Try
        If (CType(enmErr, Integer) < 0) Then
            m_strLastErr = VLC_Err(CType(enmErr, Integer))
            Return enmErr
        End If
        ' OK
        Return Err.Success
    End Function

    Public Function SetVariable(ByVal strName As String, ByVal Value As Int32) As Err
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return Err.NoInit
        End If
        Dim enmErr As Err = Err.Success
        Try
            ' create vlc value
            Dim val As vlc_value_t = New vlc_value_t
            val.i_int = Value
            ' set variable
            enmErr = VLC_VariableSet(m_iVlcHandle, strName, val)
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return Err.Execption
        End Try
        If (CType(enmErr, Integer) < 0) Then
            m_strLastErr = VLC_Err(CType(enmErr, Integer))
            Return enmErr
        End If
        ' OK
        Return Err.Success
    End Function

    Public Function GetVariable(ByVal strName As String, ByRef Value As Integer) As Err
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return Err.NoInit
        End If
        Dim enmErr As Err = Err.Success
        Try
            ' create vlc value
            Dim val As vlc_value_t = New vlc_value_t
            ' set variable
            enmErr = VLC_VariableGet(m_iVlcHandle, strName, val)
            Value = val.i_int
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return Err.Execption
        End Try
        If (CType(enmErr, Integer) < 0) Then
            m_strLastErr = VLC_Err(CType(enmErr, Integer))
            Return enmErr
        End If
        ' OK
        Return Err.Success
    End Function

    Public Function ToggleFullscreen() As Err
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return Err.NoInit
        End If
        Dim enmErr As Err = Err.Success
        Try
            enmErr = VLC_FullScreen(m_iVlcHandle)
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return Err.Execption
        End Try
        If (CType(enmErr, Integer) < 0) Then
            m_strLastErr = VLC_Err(CType(enmErr, Integer))
            Return enmErr
        End If
        ' OK
        Return Err.Success
    End Function


    Public Function PressKey(ByVal strKey As String) As Err
        If (m_iVlcHandle = -1) Then
            m_strLastErr = "LibVlc is not initialzed"
            Return Err.NoInit
        End If
        Dim enmErr As Err = Err.Success
        Try
            ' create vlc value
            Dim valKey As vlc_value_t = New vlc_value_t
            ' get variable
            enmErr = VLC_VariableGet(m_iVlcHandle, strKey, valKey)
            If (enmErr = Err.Success) Then
                ' set pressed
                enmErr = VLC_VariableSet(m_iVlcHandle, "key-pressed", valKey)
            End If
        Catch ex As Exception
            m_strLastErr = ex.Message
            Return Err.Execption
        End Try
        If (CType(enmErr, Integer) < 0) Then
            m_strLastErr = VLC_Err(CType(enmErr, Integer))
            Return enmErr
        End If
        ' OK
        Return Err.Success
    End Function

    Private Function QueryVlcInstallPath() As String
        ' open registry
        Dim regkeyVlcInstallPathKey As RegistryKey = Registry.LocalMachine.OpenSubKey("SOFTWARE\VideoLAN\VLC")
        If (regkeyVlcInstallPathKey Is Nothing) Then
            Return ""
        End If
        'Return CType(regkeyVlcInstallPathKey.GetValue("InstallDir", ""), String)
        Return ""
    End Function


    Private Sub wndOutput_Resize(ByVal sender As Object, ByVal e As EventArgs)
        If (m_iVlcHandle <> -1) Then
            SetVariable("conf::width", m_wndOutput.ClientRectangle.Width)
            SetVariable("conf::height", m_wndOutput.ClientRectangle.Height)
        End If
    End Sub


End Class